<!DOCTYPE html>
<html lang="en">
  <head>
    <title>hello-dom</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script>
      console.log(document.readyState);
    </script>
    <style>
      img {
        margin-top: 10px;
        width: 100px;
      }
      .overflow {
        height: 100px;
        overflow: scroll;
      }
    </style>
  </head>
  <body>
    <div id="timestamp"></div>
    <a href="javascript:void(window.open('about:blank'))">open</a>
    <a href='javascript:var e = "", r = ""; do { e = prompt("Expression" + e + "\n" + r + "\n", e); try { r = "Result:" + eval(e); } catch(ex) { r = ex; } } while(e); void(0);'>javascript</a>
    <button id="open-modal" type="button">open modal</button>
    <form id="user">
      <!-- form -->
    </form>
    <form id="event">
      <input id="user-radio" type="checkbox" />
    </form>
    <img src="" style="margin-left: 10px;" />
    <div class="overflow">
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
      <p>hello</p>
    </div>
    <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<g id="Brightness">
	<g>
		<path style="fill-rule:evenodd;clip-rule:evenodd;" d="M8,2c0.552,0,1-0.448,1-1c0-0.552-0.448-1-1-1C7.448,0,7,0.448,7,1
			C7,1.552,7.448,2,8,2z M3,12c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C4,12.448,3.552,12,3,12z M1,7
			C0.448,7,0,7.448,0,8c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C2,7.448,1.552,7,1,7z M3,4c0.552,0,1-0.448,1-1
			c0-0.552-0.448-1-1-1C2.448,2,2,2.448,2,3C2,3.552,2.448,4,3,4z M13,12c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1
			c0.552,0,1-0.448,1-1C14,12.448,13.552,12,13,12z M15,7c-0.552,0-1,0.448-1,1c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1
			C16,7.448,15.552,7,15,7z M8,4C5.791,4,4,5.791,4,8c0,2.209,1.791,4,4,4c2.209,0,4-1.791,4-4C12,5.791,10.209,4,8,4z M8,10
			c-1.105,0-2-0.895-2-2c0-1.105,0.895-2,2-2c1.105,0,2,0.895,2,2C10,9.105,9.105,10,8,10z M8,14c-0.552,0-1,0.448-1,1
			c0,0.552,0.448,1,1,1c0.552,0,1-0.448,1-1C9,14.448,8.552,14,8,14z M13,4c0.552,0,1-0.448,1-1c0-0.552-0.448-1-1-1
			c-0.552,0-1,0.448-1,1C12,3.552,12.448,4,13,4z"/>
	</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

    <ul id="myList"></ul>
    <ul id="yourList"></ul>
    <ul id="histList"></ul>
    <a id="link" name="link1" href="/"></a>
    <div id="first" style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <div style="height:300px">a</div>
    <button id="button">scroll</button>
    <a class="up" style="position: fixed; right: 10px; bottom: 10px;">UP</a>
    <script>
      function load (fn) {
        function firstLoaded(fn) {
          load.isReady = true;
          return fn;
        }
        if (load.isReady) {
          window.setTimeout(fn, 0);
        } else if (window.addEventListener) {
          window.addEventListener('load', firstLoaded(fn), false);
        } else if (window.attachEvent) {
          window.attachEvent('load', firstLoaded(fn));
        } else {
          window.onload = fn;
        }
      };
      load.isReady = false;
      window.$ = load;
      function parseURL(url) {
        var a = document.createElement('a');
        a.setAttribute('href', url);
        return {
          protocol: a.protocol,
          host: a.host,
          hostname: a.hostname,
          port: a.port,
          pathname: a.pathname,
          hash: a.hash,
          search: a.search,
        };
      }


      const Event = (function() {
        return {
          on(ele, eventName, handler) {
            if (ele.addEventListener) {
              ele.addEventListener(eventName, handler, false);
            }
            if (!ele._eventList) {
              ele._eventList = {};
            }
            if (!ele._eventList[eventName]) {
              ele._eventList[eventName] = [];
            }
            ele._eventList[eventName].push(handler);
          },

          removeHandler(ele, eventName, handler) {
            if (ele.removeEventListener) {
              ele.removeEventListener(eventName, handler, false);
            }
            if (ele._eventList && (ele._eventList[eventName] instanceof Array)) {
              const handlers = ele._eventList[eventName];
              handlers.some((item, index) => {
                if (item === handler) {
                  handlers.splice(index, 1);
                  return true;
                }
                return false;
              });
            }
          },
          removeAll(ele) {
            const _this = this;
            const toString = Object.prototype.toString.call;
            if (ele && ele._eventList && toString(ele._eventList).toLowerCase() === '[object object]') {
              const target = ele._eventList;
              for(let key in target) {
                if (target.hasOwnProperty(key)) {
                  _this.removeByEventName(ele, key);
                }
              }
            }
          },
          removeByEventName(ele, eventName) {
            if (ele && ele.removeEventListener && ele._eventList) {
              const handlers = ele._eventList[eventName];
              handlers || handlers.forEach((item) => {
                ele.removeEventListener(eventName, item, false);
              });
              ele._eventList[eventName] = [];
            }
          }
        };
      })();

      function clone(ele, deep) {
        if (ele.cloneNode) {
          const cloneEle = ele.cloneNode(deep);
          Event.removeAll(cloneEle);
          return cloneEle;
        }
      }


      $(function() {
        console.log(document.readyState);
        var timestamp  = document.getElementById('timestamp');
        if (timestamp.firstChild === null) {
          timestamp.appendChild(document.createTextNode(Date.now().toString()));
        }
        timestamp.style.backgroundColor = "yellow";
        timestamp.className = "hightlight";
        timestamp.onclick = function() {
          this.innerHTML = Date.now().toString();
        };
        console.log(document.compatMode === 'CSS1Compat' ? '标准模式' : '');
        console.log(parseURL(location.href));
        var up = document.querySelector('.up');
        up.onclick = function() {
          location.href = "#first";
        };
        console.log(navigator.userAgent);
        var first = document.getElementById('first');
        var parent = document.getElementsByTagName('body')[0];
        var newChild = document.createElement('p');
        newChild.innerText = `屏幕宽度:${screen.width},
        屏幕高度:${screen.height},
        可用宽度:${screen.availWidth},
        可用高度:${screen.availHeight}`;
        parent.insertBefore(newChild, first);
        var openmodal = document.getElementById('open-modal');
        openmodal.onclick = function() {
          if (window.showModalDialog) {
            window.showModalDialog('modal.html');
          } else {
            window.open('modal.html', 'modal', "height=200, width=400, top=0, left=0, toolbar=no, menubar=no, location=no, status=no, scrollbars=no");
          }
        };
        console.log(HTMLCollection.prototype instanceof Array); // HTMLCollection对象是对象数组
        console.log(window.user, document.forms);
        console.log(window.link, document.links.link1);
        console.log(window.link.nodeType);
        console.log(document.nodeType);
        var nodeList = document.forms.user.childNodes;
        [].forEach.call(nodeList, function(node) {
          if (node.nodeType === Node.COMMENT_NODE) { // 最好用数字去匹配因为不是所有浏览器都支持
            console.log("COMMENT_NODE" + node);
          }
          if (node.nodeType === Node.TEXT_NODE) {
            console.log("TEXT_NODE" + node);
          }
        });
        var div = document.createElement('div');
        document.forms.user.appendChild(div);
        document.forms.user.insertBefore(div, null);
        document.forms.user.insertBefore(document.createElement('p'), div);
        // replaceChild将会移除div在文档中的所有引用关系.然后将user.children[0]中的引用关系全部替换成div
        document.forms.user.replaceChild(div, window.user.children[0]);
        // 移除user当中的第一个Element
        document.forms.user.removeChild(window.user.children[0]);
        // 添加两个文本节点
        document.forms.user.appendChild(document.createTextNode('hello'));
        document.forms.user.appendChild(document.createTextNode('world'));
        console.log(document.documentElement === document.firstElementChild);
        console.log(Document.isPrototypeOf(HTMLDocument));
        console.log(document.doctype instanceof DocumentType);
        console.log(document.title);
        document.title = 'hello';
        console.log(document.title);
        console.log(document.URL);
        console.log(document.domain);
        console.log(document.referrer);

        // DocumentFragment
        // DocumentFragment是轻量级的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源
        // DocumentFragment很适合操作复杂DOM,然后一次性插入
        var start1 = Date.now();
        var fragement = document.createDocumentFragment();
        var myList = document.getElementById('myList');
        for (var i = 0; i < 1000; i += 1) {
          var li = document.createElement('li');
          li.appendChild(document.createTextNode(`item${i}`));
          fragement.appendChild(li);
        }
        myList.appendChild(fragement);
        console.log(`DocumentFragment spent ${Date.now() - start1} ms`);
        
        var start2 = Date.now();
        var yourList = document.getElementById('yourList');
        for (var j = 0; j < 1000; j += 1) {
          var li = document.createElement('li');
          li.appendChild(document.createTextNode(`item${j}`));
          yourList.appendChild(li);
        }
        console.log(`Add one by one spent ${Date.now() - start2} ms`);
       
       var start3 = Date.now();
       var hisList = document.getElementById('histList');
       var f1 = document.createDocumentFragment();
       var f2 = document.createDocumentFragment();
       var f3 = document.createDocumentFragment();
       var parts = 10;
       var nums = 1000;
       var f;
       for (var m = 0, n = 0; m < nums; m += 1) {
         if ( m === (nums / parts) * n  ) {
           if (f) {
             hisList.appendChild(f);
           }
           f = document.createDocumentFragment();
           n += 1;
         }
         var li = document.createElement('li');
         li.appendChild(document.createTextNode(`item${m}`));
         f.appendChild(li);
       }
       hisList.appendChild(f);
       console.log(`Split to ${parts} part spent ${Date.now() - start3}ms`);

        // 获取元素特性的方式
        var attr = document.createAttribute('align');
        attr.value = 'left';
        attr.specified = false;
        myList.setAttributeNode(attr);
        console.log(myList.getAttribute('align'));
        console.log(myList.getAttributeNode('align').value);
        console.log(myList.attributes['align'].value);

        // 动态插入脚本
        // 插入外部文件
        function loadScript(url) {
          var script = document.createElement('script');
          script.src = url;
          script.type = 'text/javascript';
          document.body.appendChild(script);
        }
        // 插入行内代码
        function loadScriptString(code) {
          var script = document.createElement('script');
          script.type = 'text/javascript';
          try {
            script.appendChild(document.createTextNode(code)); // IE will get wrong
          } catch (ex) {
            script.text = code;
          }
          document.body.appendChild(script);
        }

        loadScript('https://cdn.bootcss.com/react/15.6.1/react.js');
        
        function loadStyle(url) {
          var style = document.createElement('link');
          style.type = 'text/css';
          style.rel = 'stylesheet';
          style.href = url;
          var head = document.head || document.getElementsByTagName('head')[0];
          head.appendChild(style);
        }
        function loadStyleString(style) {
          var style = document.createElement('style');
          style.type = 'text/css';
          try {
            style.appendChild(document.createTextNode(style));
          } catch (ex) {
            style.styleSheet.cssText = style;
          }
          // document.head是HTML5新增, 目前IE9+支持
          var head = document.head || document.getElementsByTagName('head')[0];
          head.appendChild(style);
        }
        loadStyle('https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap-grid.css');

        // 操作表格
        var table = document.createElement('table');
        table.border = 1;
        table.width = '100%';
        var tBody = table.createTBody();
        var r1 = tBody.insertRow(0);
        var c1 = r1.insertCell(0);
        c1.appendChild(document.createTextNode('cell 1, 1'));
        var c2 = r1.insertCell(1);
        c2.appendChild(document.createTextNode('cell 1, 2'));
        var c3 = r1.insertCell(2);
        c3.appendChild(document.createTextNode('cell 1, 3'));
        window.user.appendChild(table);

        function matchesSelector(element, selector) {
          if (element.matchesSelector) {
            return element.matchesSelector(selector);
          } else if (element.msMatchesSelector) {
            return element.msMatchesSelector(selector);
          } else if (element.mozMatchesSelector) {
            return element.mozMatchesSelector(selector);
          } else if (element.webkitMatchesSelector) {
            return element.webkitMatchesSelector(selector);
          } else {
            throw new Error('Not Supported');
          }
        }
        // IE10+支持classList (有add, contains, remove, toggle方法)
        document.getElementById('timestamp').classList.toggle('hightlight');
        
        console.log(document.hasFocus());

        function parseHTML(html) {
          var tmp = document.createElement('div');
          if (tmp.innerText) {
            tmp.innerText = html;
          } else {
            tmp.textContent = html;
          }
          return tmp.innerHTML;
        }

        window.user.innerHTML = parseHTML('<div>Hello</div>');
        var svg = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'svg')[0]; // DOM2
        console.log(svg.isDefaultNamespace('http://www.w3.org/2000/svg'));
        console.log(svg.lookupNamespaceURI('http://www.w3.org/2000/svg'));
        var ns = document.createElementNS('http://www.w3.org/2000/svg', 's:svg'); // NS -> NameSpace
        document.images[0].appendChild(ns);
        console.log(document.images[0].firstElementChild.namespaceURI);

        console.log(document.images[0].style.margin);
        console.log(document.defaultView.getComputedStyle(document.images[0], null)['margin']);

        function scroll(ele, time, distance) {
          var originTop = ele.scrollTop;
          var dis = ele.scrollTop < distance ? ele.scrollTop : distance;
          var fps = 60;
          var inter = 1000 / fps;
          var nums = time / inter;
          var counter = setInterval(function() {
            if ((originTop - ele.scrollTop) < dis) {
              ele.scrollTop = ele.scrollTop - parseInt(distance / nums);
            } else {
              clearInterval(counter);
            }
          }, inter);
        }
        window.button.onclick = function() {
          scroll(document.body, 500, document.body.scrollTop);
        };
        var overflow = document.querySelector('.overflow');
        console.log(`clientWidth不包括滚动条${overflow.clientWidth === overflow.offsetWidth}`);
        var PHASE_MAP = {
          '1': '处于捕获阶段',
          '2' : '处于目标对象',
          '3' : '处于冒泡阶段',
        };
        document.body.addEventListener('click', function(event) {
          console.log(`Body ${PHASE_MAP[event.eventPhase]}`);
        }, false);
        document.body.addEventListener('click', function(event) {
          console.log(`Body ${PHASE_MAP[event.eventPhase]}`);
          console.log(event.currentTarget);
        }, true);
        document.getElementById('user-radio').addEventListener('click', function(event) {
          console.log(`Radio ${PHASE_MAP[event.eventPhase]}`);
          console.log(event.currentTarget);
        }, false);
      });
    </script>
  </body>
</html>